To make MongoDB database manipulation easy, we can use the Mongoose NPM package to make working with MongoDB databases easier.
In this article, we’ll look at how to use Mongoose to manipulate our MongoDB database.
Errors in Pre Hooks
We can raise errors in pre hooks in various ways.
For example, we can write:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const schema = new Schema({
name: { type: String, required: true },
age: Number
});
schema.pre('save', (next) => {
const err = new Error('error');
next(err);
});
const Kitten = connection.model('Kitten', kittenSchema);
}
run();
to pass an Error
instance in the next
method.
Also, we can return a promise:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const kittenSchema = new Schema({
name: { type: String, required: true },
age: Number
});
schema.pre('save', (next) => {
const err = new Error('error');
return Promise.reject(err);
});
const Kitten = connection.model('Kitten', kittenSchema);
}
run();
Or we can throw an error:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const schema = new Schema({
name: { type: String, required: true },
age: Number
});
schema.pre('save', (next) => {
throw new Error('error');
});
const Kitten = connection.model('Kitten', kittenSchema);
}
run();
Post Middleware
Post middlewares are run after the hooked method and all its pre middleware are run.
For example, we can write:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const schema = new Schema({
name: { type: String, required: true },
age: Number
});
schema.post('init', (doc) => {
console.log('%s has been initialized from the db', doc._id);
});
schema.post('validate', (doc) => {
console.log('%s has been validated (but not saved yet)', doc._id);
});
schema.post('save', (doc) => {
console.log('%s has been saved', doc._id);
});
schema.post('remove', (doc) => {
console.log('%s has been removed', doc._id);
});
const Kitten = connection.model('Kitten', kittenSchema);
}
run();
We added post middlewares for the init
, validate
, save
, and remove
operations that are run after the given document operations.
Async Post Hooks
We can add async post hooks. We just need to call next
to proceed to the next post hook:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const schema = new Schema({
name: { type: String, required: true },
age: Number
});
schema.post('save', (doc, next) => {
setTimeout(() => {
console.log('post1');
next();
}, 10);
});
schema.post('save', (doc, next) => {
console.log('post2');
next();
});
const Kitten = connection.model('Kitten', schema);
}
run();
We call the next
function in the setTimeout
callback to proceed to the next post middleware.
Define Middleware Before Compiling Models
We have to define middleware before we create the model with the schema for it to fire.
For example, we can write:
async function run() {
const { createConnection, Schema } = require('mongoose');
const connection = createConnection('mongodb://localhost:27017/test');
const schema = new Schema({ name: String });
schema.pre('save', () => console.log('pre save called'));
const User = connection.model('User', schema);
new User({ name: 'test' }).save();
}
run();
We created the schema and then added a save
pre middleware right after we defined the schema and before the model is created.
This way, the callback in the pre
method will be run when we create a document with the model.
Conclusion
We can add post middlewares and be careful where we define the model.